#include "Function.h"
#include "Class.h"
#include "FunctionList.h"

#include "Reflection/FunctionType.h"


CFunction::CFunction(
    CFunctionList *InParentList
    , const CString &InName
    , const SDecoratedType& InReturnType
    , const TVector<SDecoratedType>& InParameterTypes
    , TMap<EFunctionFlags, SReflectionMetaDataValue> InMetaData
    )
{
    OwnerClass=InParentList;
    ReturnType = InReturnType;
    ParameterTypes = InParameterTypes;
    Name = InName;

    ID.TypeID=InParentList->GetParentType()->ID;
    ID.FuncitonIndex=InParentList->AddFunction(this);

    // FunctionType= CFunctionTypeGeneralized::FindFunctionType(InReturnType,InParameterTypes);
    // if(!FunctionType)
    // {
    //     FunctionType =new CFunctionTypeGeneralized(InReturnType,InParameterTypes);
    // }
}

CType *CFunction::GetOwnerType()
{
    return OwnerClass->GetParentType();
}

CString CFunction::GetConstructorName()
{
    return U".Ctor";
}

void CFunction::SetCppBody(const std::function<CAny(const TVector<CAny>&)> & InFunction)
{
    Functor = std::make_unique<CCPPFunctionBody>(InFunction);
}

CAny CFunction::Invoke(const TVector<CAny> &InArgs)
{
   if(!Functor)
    {
        assert(false && "Low level error: no functor");
    }

    return Functor->Invoke(InArgs);
}

void CFunction::MarkAsVirtual()
{
    bIsVirtual=true;

    //add virtual function to class
    OwnerClass->VirtualFunctionTable.Add(this->ID);
}

bool CFunction::CanUseInScript()
{
    return !MetaData.Contains(EFunctionFlags::F_NotInScript);
}


bool CFunction::IsConstructor()
{
    return Name==GetConstructorName();   
}

CAny CCPPFunctionBody::Invoke(const TVector<CAny> &InArgs)
{
    return Function(InArgs);
}
